Skip to content

Deneb produce blockv3#12708

Merged
rkapka merged 10 commits intodevelopfrom
deneb-produce-blockv3
Sep 1, 2023
Merged

Deneb produce blockv3#12708
rkapka merged 10 commits intodevelopfrom
deneb-produce-blockv3

Conversation

@james-prysm
Copy link
Contributor

@james-prysm james-prysm commented Aug 8, 2023

What type of PR is this?

Feature

What does this PR do? Why is it needed?

implements in #12248

@james-prysm james-prysm force-pushed the deneb-produce-blockv3 branch from 4ef2eeb to 46478d9 Compare August 9, 2023 00:54
type Deposit struct {
Proof []string `json:"proof" validate:"required"`
Data DepositData `json:"data" validate:"required"`
Proof []string `json:"proof" validate:"required,dive,hexadecimal"`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it worth adding this check for hexadecimal here? we have to convert it anyways

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good question. Actually our decoding error message is far superior than the one from the validate package. For now we can leave it, but we should reevaluate if we even want to use validate since we need to decode anyway.

@james-prysm james-prysm marked this pull request as ready for review August 10, 2023 18:05
@james-prysm james-prysm requested a review from a team as a code owner August 10, 2023 18:05
@james-prysm james-prysm requested review from saolyn and removed request for a team August 10, 2023 18:05
@james-prysm
Copy link
Contributor Author

I will squish commits and fix any rebasing needed through review

type Phase0ProduceBlockV3Response struct {
Version string `json:"version" validate:"required"`
ExecutionPayloadBlinded bool `json:"execution_payload_blinded"`
ExeuctionPayloadValue string `json:"exeuction_payload_value"`
Copy link
Contributor

@rkapka rkapka Aug 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: Exeuction

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file name is too generic. What's the difference between structs.go and api_structs.go? I would name this one structs_block.go to let know blocks are defined here.

Comment on lines +780 to +784
errJson := &http2.DefaultErrorJson{
Message: "slot is required",
Code: http.StatusBadRequest,
}
http2.WriteError(w, errJson)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can use http2.HandleError here and everywhere else to make the code smaller

http2.WriteError(w, errJson)
return
}
slot, err := strconv.ParseUint(rawSlot, 10, 64)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better to write this instead:

slot, valid = shared.ValidateUint(w, "Slot", rawSlot)
if !valid {
	return
}

return
}
if optimistic {
http2.HandleError(w, "The node is currently optimistic and cannot serve validators", http.StatusInternalServerError)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use 503 Status Unavailable here

Comment on lines +906 to +907
w.Header().Set(api.ExecutionPayloadBlindedHeader, fmt.Sprintf("%v", isBlinded))
w.Header().Set(api.ExecutionPayloadValueHeader, fmt.Sprintf("%d", payloadValue))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can set these headers immediately after you receive the response from the v1alpha1 server. This will reduce duplication and you will not need to pass isBlinded anymore.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i set it but it's still used in the response, moved it outside

Comment on lines +873 to +840
blindedBellatrixBlock, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_BlindedBellatrix)
if ok {
handleProduceBlindedBellatrixV3(isSSZ, blindedBellatrixBlock, w, validate, v1alpha1resp.IsBlinded, v1alpha1resp.PayloadValue)
return
}
bellatrixBlock, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_Bellatrix)
if ok {
handleProduceBellatrixV3(isSSZ, bellatrixBlock, w, validate, v1alpha1resp.IsBlinded, v1alpha1resp.PayloadValue)
return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be inside a conditional

if v1alpha1resp.IsBlinded {
	// check blinded
} else {
	// check unblinded
}

same for capella and deneb

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you mean by this shouldn't it match the type check?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I mean is that it doesn't make sense to type check for a blinded block when v1alpha1resp.IsBlinded == false and vice versa.

http2.HandleError(w, err.Error(), http.StatusInternalServerError)
return
}
if err = validate.Struct(block); err == nil {
Copy link
Contributor

@rkapka rkapka Aug 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not validate the response. You normally only validate requests. Also this code is incorrect because nothing will happen and 200 will be returned when error is not nil.

http2.WriteJson(w, &Phase0ProduceBlockV3Response{
Version: version.String(version.Phase0),
ExecutionPayloadBlinded: false,
ExeuctionPayloadValue: fmt.Sprintf("%d", payloadValue), // mev not available at this point
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does this comment mean?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking since it's local build it's not available 🤔 but maybe i'm wrong in that assumption

package beacon

type Phase0ProduceBlockV3Response struct {
Version string `json:"version" validate:"required"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As stated in another place, I would not add validate to responses nor would I validate them. A validation error will return 400 Bad Request, but it's not the user's request that was incorrect.

Copy link
Collaborator

@terencechain terencechain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My only feedback is today we can get the value from builder payload, we can't get the value from local payload. It seems the natural progression is to add value to local payload ExecutionData. Doing so, we can remove values for block

type BeaconBlockBody struct {
version int
isBlinded bool
valueInGwei uint64
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think valueInGwei should either be inside the ExecutionData or BeaconBlock. ExecutionData is more appropriate but I'd hate to make you do this in this PR. Feel free to do this in another PR or open an issue for someone else to do it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let me think about that see if it'd be better to move it or clean this one up

}

message GenericBeaconBlock {

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert this line?

// If we can't get the builder value, just use local block.
if higherValueBuilder && withdrawalsMatched { // Builder value is higher and withdrawals match.
blk.SetBlinded(true)
blk.SetValueInGwei(builderValueGwei)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to move this before the return nil after the else

Comment on lines +120 to +125
blk.SetBlinded(false)
localPayloadValue, err := localPayload.ValueInGwei()
if err == nil {
blk.SetValueInGwei(localPayloadValue)
}
return blk.SetExecution(localPayload)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no local payload value for Bellatrix, I'd just remove these. Will love to remove any complexity

Comment on lines +131 to +134
localPayloadValue, err := localPayload.ValueInGwei()
if err == nil {
blk.SetValueInGwei(localPayloadValue)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. We can remove these

func (bs *Server) ProduceBlockV3(w http.ResponseWriter, r *http.Request) {
ctx, span := trace.StartSpan(r.Context(), "validator.ProduceBlockV3")
defer span.End()
if ok := bs.checkSync(r.Context(), w); !ok {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should pass ctx inside. Also, can you add a new line after defer span.End()?

if rawSkipRandaoVerification == "true" {
randaoReveal = primitives.PointAtInfinity
} else {
rr, err := hexutil.Decode(rawRandaoReveal)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok that's true... In that case maybe let's return bytes from shared.ValidateHex. What do you think? And inside the function use hexutil.Decode instead of bytesutil.IsHex

}

func produceBlockV3(context context.Context, bs *Server, w http.ResponseWriter, r *http.Request, v1alpha1req *eth.BlockRequest) {
ctx, span := trace.StartSpan(context, "validator.ProduceBlockV3.internal")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this useful? Same comment for other spans in private functions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm maybe not maybe I should just pass it down

Comment on lines +873 to +840
blindedBellatrixBlock, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_BlindedBellatrix)
if ok {
handleProduceBlindedBellatrixV3(isSSZ, blindedBellatrixBlock, w, validate, v1alpha1resp.IsBlinded, v1alpha1resp.PayloadValue)
return
}
bellatrixBlock, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_Bellatrix)
if ok {
handleProduceBellatrixV3(isSSZ, bellatrixBlock, w, validate, v1alpha1resp.IsBlinded, v1alpha1resp.PayloadValue)
return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I mean is that it doesn't make sense to type check for a blinded block when v1alpha1resp.IsBlinded == false and vice versa.

log.WithError(err).Error("Checking for SSZ failed, defaulting to JSON")
isSSZ = false
}
v1alpha1resp, err := bs.V1Alpha1ValidatorServer.GetBeaconBlock(r.Context(), v1alpha1req)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use ctx

@james-prysm james-prysm force-pushed the deneb-produce-blockv3 branch 3 times, most recently from db2eae1 to 7caf026 Compare August 15, 2023 20:50
@james-prysm james-prysm force-pushed the deneb-produce-blockv3 branch 3 times, most recently from c622bbd to ca3766f Compare August 16, 2023 20:22
rkapka
rkapka previously approved these changes Aug 17, 2023
@kasey kasey force-pushed the deneb-integration branch 2 times, most recently from 963fefc to ce697f3 Compare August 23, 2023 21:28
@james-prysm james-prysm force-pushed the deneb-produce-blockv3 branch from 2926e2b to 811104d Compare August 24, 2023 20:45
@james-prysm james-prysm force-pushed the deneb-produce-blockv3 branch 2 times, most recently from 261d8ee to 65d310e Compare August 25, 2023 15:15
@james-prysm james-prysm force-pushed the deneb-produce-blockv3 branch from 65d310e to 065368e Compare August 25, 2023 15:18
}

// DecodeWithLength takes a string and a length and validates the hex while returning an error
func DecodeWithLength(s string, length int) ([]byte, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rename it to DecodeHexWithLength. Otherwise the caller will have to go into the function to understand it.

}

// DecodeWithMaxLength takes a string and a max byte length and validates the hex while returning an error
func DecodeWithMaxLength(s string, length int) ([]byte, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, I would rename to DecodeHexWithMaxLength

Comment on lines +3087 to +3090
if !math.IsValidUint256(uint256) {
return nil, errors.New("is")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error message is incomplete. But do we even have to validate this once ok passes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh weird ok not sure how that cut off will fix

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments on this file:

  • It would be nice to use NewDecodeError where possible. As a small nitpick, in other conversion code we do not add the name of the object to the error message. So instead of writing NewDecodeError(err, phase0SignedBeaconBlock.Signature) we write NewDecodeError(err, Signature). This is mostly because a user does not send anything called phase0SignedBeaconBlock in the request.
  • In https://github.com/prysmaticlabs/prysm/pull/12735/files#diff-a545f9cb2d7ef7f156c12cbef6fd7dc46f45f9e0000681fd79d59c35c38177c9 I used a naming scheme XXXFromConsensus - can you use the same instead of ConvertXXX?
  • I don't particularly like the word Internal in exported function names. From my experience "internal" often means that the function is internal to a module. Maybe we could change this to XXXFromConsensus and XXXToConsensus. In case of exits that would become ExitsFromConsensus and ExitsToConsensus.

Base automatically changed from deneb-integration to develop August 31, 2023 13:41
@prestonvanloon prestonvanloon dismissed rkapka’s stale review August 31, 2023 13:41

The base branch was changed.

@james-prysm james-prysm force-pushed the deneb-produce-blockv3 branch 5 times, most recently from 179b3c0 to 4a9ab6b Compare September 1, 2023 02:08
@james-prysm james-prysm force-pushed the deneb-produce-blockv3 branch from 4a9ab6b to 722f540 Compare September 1, 2023 03:37
@rkapka rkapka merged commit 9a7393a into develop Sep 1, 2023
@rkapka rkapka deleted the deneb-produce-blockv3 branch September 1, 2023 10:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants